home *** CD-ROM | disk | FTP | other *** search
/ QuickTime 2.0 Developer Kit / QuickTime 2.0 Developer Kit.iso / pc / windows / qtw_201 / setup / samples / navigatr / navigatr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-19  |  17.1 KB  |  603 lines

  1.  
  2.  
  3. // ---------------------------------------------------------------------
  4. //
  5. // NAVIGATR.C   - QuickTime for Windows
  6. //
  7. //                Version 1.0
  8. //
  9. //                (c) Copyright 1988-1994 Apple Computer, Inc. All Rights Reserved.
  10. //
  11. // ---------------------------------------------------------------------
  12.  
  13.  
  14. #include <windows.h>
  15. #include <commdlg.h>
  16. #include <qtw.h>
  17. #include <dos.h>
  18. #include <math.h>
  19. #include <direct.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <sys\types.h>
  24. #include <sys\stat.h>
  25. #include "navigatr.hr" 
  26. #include "fileexts.rh"
  27.  
  28. #define MAX_DELAY 500
  29. #define REPEAT_PAN 1
  30. #define SQR(x) ((x)*(x))
  31.  
  32. long FAR PASCAL __export WndProc (HWND, UINT, WPARAM, LPARAM);
  33. static int NEAR MyGetZone (HWND);
  34. static LONG NEAR MyPanMovie (HWND, int);
  35. static UINT NEAR MyCalcDelay (HWND, int);
  36. static VOID NEAR MyShowFrame (HWND);
  37. static int NEAR Flip16 (int);
  38.  
  39. static MovieFile mfMovie;
  40. static Movie mMovie;
  41. static MovieController mcController;
  42. static HWND hWnd;
  43. static HCURSOR hNormal;
  44. static HCURSOR hCursor[CUR_MAX];
  45. static RECT rcZone[CUR_MAX];
  46. static int cxZone, cyZone;
  47. static RECT rcMovie;
  48. static char szAppName[] = "NAVIGATR";
  49. static short cxFrame, cyFrame, bBidirectional, sLoopSize, sScaleFactor;
  50. static LONG xFrame, yFrame, lFrame;
  51. static BOOL bNAVG, bNAVg;
  52.  
  53.  
  54. // WinMain
  55. // ---------------------------------------------------------------------
  56. int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  57.    LPSTR lpszCmdParam, int nCmdShow)
  58. {
  59.     MSG msg;
  60.     WNDCLASS wndclass;
  61.     RECT rcDesktop, rcController;
  62.     char szDir[_MAX_DIR];
  63.     char szMovieTitle[_MAX_PATH];
  64.     char szMovie[_MAX_PATH];
  65.     char szTitle[_MAX_PATH];
  66.     char szFilter[_MAX_PATH];
  67.     UserData udMovie;
  68.     HGLOBAL hMem;
  69.     LONG lSize;
  70.     OPENFILENAME ofn;
  71.     struct _stat st;
  72.     short far * s;
  73.     short v;
  74.     char * p;
  75.     int i;
  76.  
  77.     // If parameter is missing, look for a movie with the same name
  78.     // as the executable. If this isn't found, use the standard
  79.     // open dialog to get a movie name
  80.  
  81.     if (lstrlen (lpszCmdParam) == 0) {
  82.         GetModuleFileName (hInstance, szMovie, sizeof (szMovie));
  83.         p = strrchr (szMovie, '.');
  84.         strcpy (p, ".MOV");
  85.         if (_stat (szMovie, &st)) {
  86.             _getcwd (szDir, sizeof (szDir));
  87.             szMovie[0] = '\0';
  88.             memset (&ofn, 0, sizeof(OPENFILENAME));
  89.             ofn.lStructSize = sizeof(OPENFILENAME);
  90.             ofn.hwndOwner = 0;
  91.             ofn.lpstrFilter = CommonGetFileFilter (hInstance, (WORD) COMMON_MOVIES_FILEEXT, szFilter, sizeof szFilter);
  92.             ofn.nFilterIndex = 1;
  93.             ofn.lpstrFile = szMovie;
  94.             ofn.nMaxFile = sizeof(szMovie);
  95.             ofn.lpstrFileTitle = szMovieTitle;
  96.             ofn.nMaxFileTitle = sizeof(szMovieTitle);
  97.             ofn.lpstrInitialDir = szDir;
  98.             ofn.lpstrTitle = "Select a Movie to Navigate";
  99.             ofn.Flags = OFN_HIDEREADONLY;
  100.             if (GetOpenFileName (&ofn) == 0)
  101.                 return 0;
  102.         }
  103.         _strupr (szMovie);
  104.     }
  105.  
  106.     // Otherwise, treat the command line parameter as the
  107.     // root directory.
  108.  
  109.     else {
  110.         lstrcpy (szMovie, lpszCmdParam);
  111.         _strupr (szMovie);
  112.     }
  113.  
  114.     // Derive the title
  115.  
  116.     _splitpath (szMovie, NULL, NULL, szTitle, NULL);
  117.     AnsiLower (szTitle);
  118.  
  119.     // Establish links to QuickTime for Windows
  120.  
  121.     if (QTInitialize (NULL)) {
  122.         MessageBox (NULL, "QTInitialize failure", szAppName, MB_OK);
  123.         return 0;
  124.     }
  125.  
  126.     // Allocate memory required for playing movies
  127.  
  128.     if (EnterMovies ()) {
  129.         MessageBox (NULL, "EnterMovies failure", szAppName, MB_OK);
  130.         return 0;
  131.     }
  132.  
  133.     // Instantiate movie
  134.  
  135.     if (OpenMovieFile (szMovie, &mfMovie, OF_READ) != noErr) {
  136.         MessageBox (NULL, "OpenMovieFile failure", szAppName, MB_OK);
  137.         PostQuitMessage (0);
  138.         return 0;
  139.     }
  140.  
  141.     NewMovieFromFile (&mMovie, mfMovie, NULL, NULL, 0, NULL);
  142.     CloseMovieFile (mfMovie);
  143.  
  144.     // Extract NAVG user data
  145.  
  146.     if (((udMovie = GetMovieUserData (mMovie)) != NULL)
  147.      && ((hMem = GlobalAlloc (GMEM_MOVEABLE, 128)) != NULL)) {
  148.  
  149.         // New format
  150.  
  151.         if (GetUserData (udMovie, &hMem, QTFOURCC('N','A','V','G'), 1, &lSize) == noErr) {
  152.             s = (short FAR *) GlobalLock (hMem);
  153.             v = *s++;
  154.             v = *s++; cxFrame = Flip16 (v);
  155.             v = *s++; cyFrame = Flip16 (v) - 1;
  156.             v = *s++; bBidirectional = ((Flip16 (v)) == 1);
  157.             v = *s++; sLoopSize = Flip16 (v);
  158.             v = *s++; sScaleFactor = Flip16 (v);
  159.             GlobalUnlock (hMem);
  160.             bNAVG = TRUE;
  161.         }
  162.  
  163.         // Old format
  164.  
  165.         else if (GetUserData (udMovie, &hMem, QTFOURCC('N','A','V','g'), 1, &lSize) == noErr) {
  166.             s = (short FAR *) GlobalLock (hMem);
  167.             v = *s++;
  168.             v = *s++; cyFrame = Flip16 (v);
  169.             v = *s++; cxFrame = Flip16 (v);
  170.             v = *s++; bBidirectional = ((Flip16 (v)) == 1);
  171.             sScaleFactor = (short) (GetMovieTimeScale (mMovie) / 60);
  172.             GlobalUnlock (hMem);
  173.             bNAVg = TRUE;
  174.         }
  175.     }
  176.  
  177.     if (hMem) GlobalFree (hMem);
  178.  
  179.     if (!bNAVG && !bNAVg) {
  180.         MessageBox (NULL, "This movie cannot be navigated!", szAppName, MB_OK);
  181.         PostQuitMessage (0);
  182.         return 0;
  183.     }
  184.  
  185.     // Initialize the starting location
  186.  
  187.     lFrame = (LONG) GetMovieDuration (mMovie) / 2;
  188.     xFrame = (lFrame / sScaleFactor) % cxFrame;
  189.     yFrame = (lFrame / sScaleFactor) / cxFrame;
  190.  
  191.     // Load the zone cursors
  192.  
  193.     hNormal = LoadCursor (NULL, IDC_ARROW);
  194.  
  195.     for (i = CUR_N; i < CUR_MAX; i++)
  196.         hCursor[i] = LoadCursor (hInstance, MAKEINTRESOURCE (i));
  197.  
  198.     // Register and create main window
  199.  
  200.     if (!hPrevInstance) {
  201.         wndclass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  202.         wndclass.lpfnWndProc = WndProc;
  203.         wndclass.cbClsExtra = 0;
  204.         wndclass.cbWndExtra = 0;
  205.         wndclass.hInstance = hInstance;
  206.         wndclass.hIcon = LoadIcon (NULL,IDI_APPLICATION);
  207.         wndclass.hCursor = hNormal;
  208.         wndclass.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH);
  209.         wndclass.lpszMenuName = NULL;
  210.         wndclass.lpszClassName = szAppName;
  211.         if (!RegisterClass (&wndclass)) {
  212.             MessageBox (NULL, "RegisterClass failure", szAppName, MB_OK);
  213.             return 0;
  214.         }
  215.     }
  216.  
  217.     hWnd = CreateWindow(szAppName, szAppName, WS_CAPTION | WS_SYSMENU |
  218.         WS_CLIPCHILDREN | WS_OVERLAPPED, CW_USEDEFAULT, CW_USEDEFAULT,
  219.         CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
  220.  
  221.     if (hWnd == NULL) {
  222.         MessageBox (NULL, "CreateWindow failure", szAppName, MB_OK);
  223.         return 0;
  224.     }
  225.  
  226.     // Instantiate the movie controller
  227.  
  228.     GetMovieBox (mMovie, &rcMovie);
  229.     OffsetRect(&rcMovie, -rcMovie.left, -rcMovie.top);
  230.     mcController = NewMovieController (mMovie, &rcMovie,
  231.         mcTopLeftMovie + mcScaleMovieToFit + mcNotVisible, hWnd);
  232.  
  233.     // Initialize the zone rectangles
  234.  
  235.     cxZone = rcMovie.right / 3;
  236.     cyZone = rcMovie.bottom / 3;
  237.  
  238.     rcZone[CUR_N].left = rcMovie.left + cxZone;
  239.     rcZone[CUR_N].right = rcMovie.right - cxZone;
  240.     rcZone[CUR_N].top = rcMovie.top;
  241.     rcZone[CUR_N].bottom = rcMovie.top + cyZone;
  242.  
  243.     rcZone[CUR_NE].left = rcMovie.right - cxZone;
  244.     rcZone[CUR_NE].right = rcMovie.right;
  245.     rcZone[CUR_NE].top = rcMovie.top;
  246.     rcZone[CUR_NE].bottom = rcMovie.top + cyZone;
  247.  
  248.     rcZone[CUR_E].left = rcMovie.right - cxZone;
  249.     rcZone[CUR_E].right = rcMovie.right;
  250.     rcZone[CUR_E].top = rcMovie.top + cyZone;
  251.     rcZone[CUR_E].bottom = rcMovie.bottom - cyZone;
  252.  
  253.     rcZone[CUR_SE].left = rcMovie.right - cxZone;
  254.     rcZone[CUR_SE].right = rcMovie.right;
  255.     rcZone[CUR_SE].top = rcMovie.bottom - cyZone;
  256.     rcZone[CUR_SE].bottom = rcMovie.bottom;
  257.  
  258.     rcZone[CUR_S].left = rcMovie.left + cxZone;
  259.     rcZone[CUR_S].right = rcMovie.right - cxZone;
  260.     rcZone[CUR_S].top = rcMovie.bottom - cyZone;
  261.     rcZone[CUR_S].bottom = rcMovie.bottom;
  262.  
  263.     rcZone[CUR_SW].left = rcMovie.left;
  264.     rcZone[CUR_SW].right = rcMovie.left + cxZone;
  265.     rcZone[CUR_SW].top = rcMovie.bottom - cyZone;
  266.     rcZone[CUR_SW].bottom = rcMovie.bottom;
  267.  
  268.     rcZone[CUR_W].left = rcMovie.left;
  269.     rcZone[CUR_W].right = rcMovie.left + cxZone;
  270.     rcZone[CUR_W].top = rcMovie.top + cyZone;
  271.     rcZone[CUR_W].bottom = rcMovie.bottom - cyZone;
  272.  
  273.     rcZone[CUR_NW].left = rcMovie.left;
  274.     rcZone[CUR_NW].right = rcMovie.left + cxZone;
  275.     rcZone[CUR_NW].top = rcMovie.top;
  276.     rcZone[CUR_NW].bottom = rcMovie.top + cyZone;
  277.  
  278.     rcZone[CUR_CENTER].left = rcMovie.left + cxZone;
  279.     rcZone[CUR_CENTER].right = rcMovie.right - cxZone;
  280.     rcZone[CUR_CENTER].top = rcMovie.top + cyZone;
  281.     rcZone[CUR_CENTER].bottom = rcMovie.bottom - cyZone;
  282.  
  283.     // Make the window just big enough for the controller
  284.  
  285.     MCGetControllerBoundsRect (mcController, &rcController);
  286.     AdjustWindowRect (&rcController, WS_CAPTION | WS_OVERLAPPED, FALSE);
  287.     OffsetRect(&rcController, -rcController.left, -rcController.top);
  288.     GetWindowRect (GetDesktopWindow (), &rcDesktop);
  289.     SetWindowPos (hWnd, 0,
  290.         (rcDesktop.right - rcController.right) / 2,
  291.         (rcDesktop.bottom - rcController.bottom) / 2,
  292.         rcController.right, rcController.bottom, SWP_NOZORDER);
  293.  
  294.     // Make the main window visible
  295.  
  296.     SetWindowText (hWnd, szTitle);
  297.     ShowWindow (hWnd, nCmdShow);
  298.     UpdateWindow (hWnd);
  299.     MCDoAction (mcController, mcActionPlay, (LPVOID) MAKELFIXED (0, 0));
  300.     SetMovieActive (mMovie, TRUE);
  301.     MyShowFrame (hWnd);
  302.     InvalidateRect (hWnd, &rcMovie, FALSE);
  303.     MCDoAction (mcController, mcActionSetFlags, (LPVOID) mcFlagsUseWindowPalette);
  304.  
  305.     // Play the movie
  306.  
  307.     while (GetMessage (&msg, NULL, 0, 0)) {
  308.         TranslateMessage (&msg);
  309.         DispatchMessage (&msg);
  310.     }
  311.  
  312.     // Destroy movie controller
  313.  
  314.     DisposeMovieController (mcController);
  315.  
  316.     // Destroy movie
  317.  
  318.     DisposeMovie (mMovie);
  319.  
  320.     // Destroy the zone cursors
  321.  
  322.     for (i = CUR_N; i <= CUR_MAX; i++)
  323.         DestroyCursor (hCursor[i]);
  324.  
  325.     // Cut the connections to QuickTime for Windows
  326.  
  327.     ExitMovies ();
  328.     QTTerminate ();
  329.  
  330.     // Return to Windows
  331.  
  332.     return msg.wParam;
  333. }
  334.  
  335.  
  336. // WndProc
  337. // ---------------------------------------------------------------------
  338. long FAR PASCAL __export WndProc (HWND hWnd, UINT message, WPARAM wParam,
  339.    LPARAM lParam)
  340. {
  341.     RECT rcClient;
  342.     PAINTSTRUCT ps;
  343.     int i;
  344.  
  345.     // Drive the movie controller
  346.  
  347.     if (message != WM_LBUTTONDBLCLK)
  348.         MCIsPlayerMessage (mcController, hWnd, message, wParam, lParam);
  349.  
  350.     // Process the windows message
  351.  
  352.     switch (message) {
  353.  
  354.         // All done!
  355.  
  356.         case WM_DESTROY:
  357.             PostQuitMessage (0);
  358.             return 0;
  359.  
  360.         // (Primitive) keyboard interface
  361.  
  362.         case WM_KEYDOWN:
  363.             switch (wParam) {
  364.                 case VK_UP:    return MyPanMovie (hWnd, CUR_N);
  365.                 case VK_DOWN:  return MyPanMovie (hWnd, CUR_S);
  366.                 case VK_LEFT:  return MyPanMovie (hWnd, CUR_W);
  367.                 case VK_RIGHT: return MyPanMovie (hWnd, CUR_E);
  368.                 default:       return 0;
  369.             }
  370.  
  371.         // Click down
  372.  
  373.         case WM_LBUTTONDOWN:
  374.             GetClientRect (hWnd, &rcClient);
  375.             ClientToScreen (hWnd, (POINT FAR *) &rcClient.left);
  376.             ClientToScreen (hWnd, (POINT FAR *) &rcClient.right);
  377.             ClipCursor (&rcClient);
  378.             SetCapture (hWnd);
  379.             i = MyGetZone (hWnd);
  380.             SetCursor (hCursor[i]);
  381.             return MyPanMovie (hWnd, i);
  382.  
  383.         // Click up
  384.  
  385.         case WM_LBUTTONUP:
  386.             KillTimer (hWnd, REPEAT_PAN);
  387.             ClipCursor (NULL);
  388.             ReleaseCapture ();
  389.             SetCursor (hNormal);
  390.             return 0;
  391.  
  392.         // Mouse movement
  393.  
  394.         case WM_MOUSEMOVE:
  395.             if (hWnd == GetCapture ())
  396.                 SetCursor (hCursor[MyGetZone(hWnd)]);
  397.             return 0;
  398.  
  399.         // In case we have to paint this movie
  400.  
  401.         case WM_PAINT:
  402.             if (!BeginPaint (hWnd, &ps))
  403.                 return 0;
  404.             EndPaint (hWnd, &ps);
  405.             return 0;
  406.  
  407.         // Repeat pan
  408.  
  409.         case WM_TIMER:
  410.             return MyPanMovie (hWnd, MyGetZone (hWnd));
  411.  
  412.     }
  413.  
  414.     // Return to Windows
  415.  
  416.     return DefWindowProc (hWnd, message, wParam, lParam);
  417. }
  418.  
  419.  
  420. // MyGetZone
  421. // ---------------------------------------------------------------------
  422. static int NEAR MyGetZone (HWND hWnd)
  423. {
  424.     POINT pt;
  425.     int i;
  426.  
  427.     // What is the current cursor position?
  428.  
  429.     GetCursorPos (&pt);
  430.     ScreenToClient (hWnd, &pt);
  431.  
  432.     // In which zone does it lie?
  433.  
  434.     for (i = CUR_N; i <= CUR_MAX; i++) {
  435.         if (PtInRect (&rcZone[i], pt))
  436.             break;
  437.     }
  438.  
  439.     // Return zone to caller
  440.  
  441.     return i;
  442.  
  443. }
  444.  
  445.  
  446. // MyPanMovie
  447. // ---------------------------------------------------------------------
  448. static LONG NEAR MyPanMovie (HWND hWnd, int i)
  449. {
  450.     // Stop any prior timer
  451.  
  452.     KillTimer (hWnd, REPEAT_PAN);
  453.  
  454.     // Calculate new position
  455.  
  456.     switch (i) {
  457.  
  458.         case CUR_N:            --yFrame; break;
  459.         case CUR_E:  ++xFrame;           break;
  460.         case CUR_S:            ++yFrame; break;
  461.         case CUR_W:  --xFrame;           break;
  462.         case CUR_NE: ++xFrame; --yFrame; break;
  463.         case CUR_SE: ++xFrame; ++yFrame; break;
  464.         case CUR_SW: --xFrame; ++yFrame; break;
  465.         case CUR_NW: --xFrame; --yFrame; break;
  466.  
  467.     }
  468.  
  469.     // Adjust for wrapping
  470.  
  471.     if (xFrame < 0)        xFrame = cxFrame - 1;
  472.     if (xFrame >= cxFrame) xFrame = 0;
  473.     if (yFrame < 0)        yFrame = 0;
  474.     if (yFrame >= cyFrame) yFrame = cyFrame - 1;
  475.  
  476.     // Now, show the right frame
  477.  
  478.     MyShowFrame (hWnd);
  479.  
  480.     // Start up again quickly ...
  481.  
  482.     SetTimer (hWnd, REPEAT_PAN, MyCalcDelay (hWnd, i), NULL);
  483.  
  484.     // Return to caller
  485.  
  486.     return 0;
  487.  
  488. }
  489.  
  490.  
  491. // MyCalcDelay
  492. // ---------------------------------------------------------------------
  493. static UINT NEAR MyCalcDelay (HWND hWnd, int i)
  494. {
  495.     POINT pt;
  496.     UINT uiDelay;
  497.  
  498.     // What is the current cursor position?
  499.  
  500.     GetCursorPos (&pt);
  501.     ScreenToClient (hWnd, &pt);
  502.  
  503.     // Calculate delay time
  504.  
  505.     switch (i) {
  506.  
  507.         case CUR_N:  uiDelay = ((pt.y - rcMovie.top) * MAX_DELAY)
  508.                        / (cyZone - rcMovie.top);
  509.                      break;
  510.  
  511.         case CUR_E:  uiDelay = ((rcMovie.right - pt.x) * MAX_DELAY)
  512.                        / (rcMovie.right - cxZone);
  513.                      break;
  514.  
  515.         case CUR_S:  uiDelay = ((rcMovie.bottom - pt.y) * MAX_DELAY)
  516.                        / (rcMovie.bottom - cyZone);
  517.                      break;
  518.  
  519.         case CUR_W:  uiDelay = ((pt.x - rcMovie.left) * MAX_DELAY)
  520.                        / (cxZone - rcMovie.left);
  521.                      break;
  522.  
  523.         case CUR_NE: uiDelay = (UINT) ((sqrt (SQR (rcMovie.right - pt.x)
  524.                        + SQR (pt.y - rcMovie.top)) * MAX_DELAY)
  525.                        / sqrt (SQR (cxZone) + SQR (cyZone)));
  526.                      break;
  527.  
  528.         case CUR_SE: uiDelay = (UINT) ((sqrt (SQR (rcMovie.right - pt.x)
  529.                        + SQR (rcMovie.bottom - pt.y)) * MAX_DELAY)
  530.                        / sqrt (SQR (cxZone) + SQR (cyZone)));
  531.                      break;
  532.  
  533.         case CUR_SW: uiDelay = (UINT) ((sqrt (SQR (pt.x - rcMovie.left)
  534.                        + SQR (rcMovie.bottom - pt.y)) * MAX_DELAY)
  535.                        / sqrt (SQR (cxZone) + SQR (cyZone)));
  536.                      break;
  537.  
  538.         case CUR_NW: uiDelay = (UINT) ((sqrt (SQR (pt.x - rcMovie.left)
  539.                        + SQR (pt.y - rcMovie.top)) * MAX_DELAY)
  540.                        / sqrt (SQR (cxZone) + SQR (cyZone)));
  541.                      break;
  542.  
  543.         default:     uiDelay = MAX_DELAY;
  544.                      break;
  545.  
  546.     }
  547.  
  548.     // Return to caller
  549.  
  550.     return uiDelay;
  551.  
  552. }
  553.  
  554.  
  555. // MyShowFrame
  556. // ---------------------------------------------------------------------
  557. static VOID NEAR MyShowFrame (HWND hWnd)
  558. {
  559.     TimeRecord tr;
  560.  
  561.     // Get the current movie time
  562.  
  563.     GetMovieTime (mMovie, &tr);
  564.  
  565.     // Is this new style?
  566.  
  567.     if (bNAVG) {
  568.         if (! bBidirectional || ((yFrame % 2) == 0))
  569.             tr.value.dwLo = ((yFrame * cxFrame) + xFrame) * sScaleFactor;
  570.         else tr.value.dwLo = ((yFrame * cxFrame) + (cxFrame - xFrame - 1)) * sScaleFactor;
  571.     }
  572.  
  573.     // Or old style?
  574.  
  575.     else if (bNAVg) {
  576.         if (! bBidirectional || ((yFrame % 2) == 0))
  577.             tr.value.dwLo = ((yFrame * cxFrame) + xFrame) * sScaleFactor;
  578.         else tr.value.dwLo = ((yFrame * cxFrame) + (cxFrame - xFrame - 1)) * sScaleFactor;
  579.     }
  580.  
  581.     // Set the new movie time
  582.  
  583.     if (MCDoAction (mcController, mcActionGoToTime, (LPVOID) &tr) != mcOK)
  584.        return;
  585.  
  586. }
  587.  
  588.  
  589. // Flip16
  590. // ---------------------------------------------------------------------
  591. #pragma optimize ("ceglnpqiw", off)
  592. static int NEAR Flip16 (int v)
  593. {
  594.  
  595.     _asm {
  596.         mov ax,v
  597.         xchg ah,al
  598.         mov v,ax
  599.     }
  600.  
  601.     return v;
  602. }
  603.